<template>
  <div class="demo">
    <!-- 视图 -->
    <div ref="chart" id="chart"></div>
    <!-- 查询表单 -->
    <div class="search-form">
      <el-form
        :inline="true"
        :model="searchForm"
        :rules="searchFormRules"
        ref="searchForm"
        class="demo-form-inline"
      >
        <!-- 关键词输入框 -->
        <el-form-item label="关键词" prop="keywords">
          <el-input
            v-model="searchForm.keywords"
            placeholder="请输入关键词"
            size="mini"
          ></el-input>
        </el-form-item>
        <!-- 关系层级选择器 -->
        <el-form-item label="关系层级" prop="level">
          <el-select
            v-model="searchForm.level"
            placeholder="关系层级"
            size="mini"
          >
            <el-option label="1" value="1"></el-option>
            <el-option label="2" value="2"></el-option>
            <el-option label="3" value="3"></el-option>
          </el-select>
        </el-form-item>
        <!-- 节点总数输入框 -->
        <el-form-item label="节点总数" prop="limit">
          <el-input
            v-model.number="searchForm.limit"
            placeholder="请输入节点总数"
            size="mini"
          ></el-input>
        </el-form-item>
        <!-- 查询按钮 -->
        <el-form-item>
          <el-button type="primary" @click="search" size="mini">查询</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script>
import {
  getVisualData,
  getNodeInfo,
  getRelaInfo
} from '@/api/visual'

export default {
  data() {
    return {
      loading: false,
      timer: null,
      chart: null,
      searchForm: {
        keywords: '桂林',
        level: 3,
        limit: 20
      },
      searchFormRules: {
        keywords: [{ required: false }],
        level: [{ required: true, message: '请选择关系层级', trigger: 'blur' }],
        limit: [
          { required: true, message: '请输入总节点数', trigger: 'blur' },
          { type: 'number', message: '请输入数字', trigger: 'blur' }
        ]
      },
      nodeList: [],
      linkList: []
    }
  },
  mounted () {
    // 初始化
    this.chart = this.echarts.init(this.$refs.chart)
    this.chart.setOption(this.option)
    this.getData()
  },
  computed: {
    option () {
      return {
        backgroundColor: new this.echarts.graphic.RadialGradient(0.3, 0.3, 0.8, [
          {
            offset: 0,
            color: '#f7f8fa'
          },
          {
            offset: 1,
            color: '#cdd0d5'
          }
        ]),
        title: {
          text: '',
          subtext: '',
          right: 10,
          bottom: 10
        },
        layoutAnimation: false,
        tooltip: {},
        legend: [
          {
            formatter:  name => {
              return this.echarts.format.truncateText(
                name,
                80,
                '14px Microsoft Yahei',
                '…'
              )
            },
            tooltip: {
              show: true
            },
            selectedMode: 'false',
            bottom: 20,
            data: ['实体', '关系']
          }
        ],
        toolbox: {
          show: true,
          feature: {
            dataView: {
              show: true,
              readOnly: true
            },
            restore: {
              show: true
            },
            saveAsImage: {
              show: true
            }
          }
        },
        animationDuration: 100,
        series: [
          {
            name: '知识图谱',
            type: 'graph',
            layout: 'force',
            animation: false,
            force: {
              // 节点之间的斥力因子
              repulsion: 50,
              // 节点受到的向中心的引力因子
              gravity: 0.001,
              // 边的两个节点之间的距离
              edgeLength: 90,
              // 显示布局的迭代动画
              layoutAnimation: true,
              // 节点的移动速度
              friction: 0.6
            },
            data: this.nodeList.map((n, i) => {
              if (i === 0) {
                return {
                  ...n,
                  x: 0,
                  y: 0,
                  draggable: 'true',
                  value: n._id,
                  id: n.category + n._id
                }
              } else {
                return {
                  ...n,
                  value: n._id,
                  draggable: 'true',
                  id: n.category + n._id
                }
              }
            }),
            links: this.linkList,
            categories: [
              {
                name: '实体'
              },
              {
                name: '关系'
              }
            ],
            focusNodeAdjacency: true,
            roam: true,
            label: {
              normal: {
                show: true,
                position: 'top'
              }
            },
            lineStyle: {
              normal: {
                color: 'source',
                curveness: 0,
                type: 'solid'
              }
            }
          }
        ]
      }
    }
  },
  destroyed() {
    clearInterval(this.timer)
  },
  methods: {
    async getData () {
      this.loading = this.$loading({
        text: '正在查询图谱数据...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })
      const res = await getVisualData(this.searchForm)
      console.log(res, '综合关系')
      // 取出所有节点ID（存在重复）
      const tpNodes = res.data.reduce((p, c) => {
        const node = c.nodes.map(n => {
          const tp = n.split('/')
          return parseInt(tp[tp.length - 1])
        })
        return p.concat(node)
      }, [])
      // 节点ID去重
      const nodeIds = Array.from(new Set(tpNodes))
      // 根据所有节点id，请求节点详情
      let promises = nodeIds.map(nodeId => getNodeInfo({ nodeId }))
      const nodeInfoResArr = await Promise.all(promises)
      // 获取所有节点列表
      this.nodeList = nodeInfoResArr.map(n => {
        return {
          ...n.data,
          symbolSize: 30,
          category: '实体'
        }
      })
      // console.log(nodeList)

      // 处理关系
      const tpRela = res.data.reduce((p, c) => {
        const rela = c.relationships.map(r => {
          const tp = r.split('/')
          return parseInt(tp[tp.length - 1])
        })
        return p.concat(rela)
      }, [])
      // 关系去重
      const relaIds = Array.from(new Set(tpRela))
      // 根据所有节点id，请求关系详情
      promises = relaIds.map(rid => getRelaInfo({ rid }))
      const relaInfoResArr = await Promise.all(promises)
      // console.log(relaInfoResArr, 'debug')
      this.nodeList.push(
        ...relaInfoResArr.map(r => {
          return {
            ...r.data,
            symbolSize: 20,
            category: '关系'
          }
        })
      )

      // 提取关系
      this.linkList = res.data.reduce((p, c) => {
        const links = []
        for (let i = 0; i < c.relationships.length; i++) {
          const pNodeArr = c.nodes[i].split('/')
          const rArr = c.relationships[i].split('/')
          const bNodeArr = c.nodes[i + 1].split('/')
          links.push({ source: '实体' + pNodeArr[pNodeArr.length - 1], target: '关系' + rArr[rArr.length - 1]})
          links.push({ source: '关系' + rArr[rArr.length - 1], target: '实体' + bNodeArr[bNodeArr.length - 1] })
        }
        return p.concat(links)
      }, [])

      console.log(this.linkList)

      this.loading.close()
      this.chart.setOption(this.option)
    },
    search () {
      this.$refs['searchForm'].validate(v => {
        if (!v) return false
        this.getData()
      })
    }
  }
}
</script>

<style lang="stylus" scoped>
.demo
  width: 100%
  height: 100%
  position: relative

#chart
  width: 100%
  height: calc(100% - 60px)

.search-form
  position: absolute
  z-index 100
  top 5px
  left 40px
  // background: red

</style>
